﻿using System;
using System.Linq;
using Croxweb.Leuphana.Models;
using System.Collections.ObjectModel;
using System.Windows.Data;
using System.ComponentModel;
using Croxweb.Leuphana.Services.MyStudyService;
using System.Windows;
using System.Windows.Threading;


namespace Croxweb.Leuphana.ViewModels
{
    public class LectureViewModel : ViewModelBase
    {
        private Lecture lecture;
        private IMyStudyService service;

        private CollectionViewSource personViewSource = new CollectionViewSource();
        private CollectionViewSource appointmentWeeklyViewSource = new CollectionViewSource();
        private CollectionViewSource appointmentSingleViewSource = new CollectionViewSource();
        private CollectionViewSource messageViewSource = new CollectionViewSource();

        private ObservableCollection<PersonViewModel> persons;
        private ObservableCollection<AppointmentViewModel> appointments;
        private ObservableCollection<MessageViewModel> messages;

        private Boolean isDataLoaded;
        private Boolean isLoading;
        private Double detailsExpanded = 96;

        public LectureViewModel()
        {
            this.lecture = new Lecture();
        }

        public LectureViewModel(Lecture lecture, IMyStudyService service)
        {
            this.lecture = lecture;
            this.service = service;
        }

        public String Title
        {
            get { return lecture.Title; }
            set
            {
                lecture.Title = value;
                NotifyPropertyChanged("Title");
            }
        }
        public String Details
        {
            get { return lecture.Details; }
            set
            {
                lecture.Details = value;
                NotifyPropertyChanged("Details");
            }
        }
        public String Goals
        {
            get { return lecture.Goals; }
            set
            {
                lecture.Goals = value;
                NotifyPropertyChanged("Goals");
            }
        }
        public String Sws
        {
            get { return lecture.Sws; }
            set
            {
                lecture.Sws = value;
                NotifyPropertyChanged("Sws");
            }
        }
        public String Url
        {
            get { return lecture.Url; }
            set
            {
                lecture.Url = value;
                NotifyPropertyChanged("Url");
            }
        }

        public ICollectionView Persons { get { return personViewSource.View; } }
        public ICollectionView WeeklyAppointments { get { return appointmentWeeklyViewSource.View; } }
        public ICollectionView SingleAppointments { get { return appointmentSingleViewSource.View; } }
        public ICollectionView Messages { get { return messageViewSource.View; } }

        public Boolean IsDataLoaded
        {
            get { return isDataLoaded; }
            set
            {
                isDataLoaded = value;
                NotifyPropertyChanged("IsDataLoaded");
            }
        }
        public Boolean IsLoading
        {
            get { return isLoading; }
            set
            {
                isLoading = value;
                NotifyPropertyChanged("IsLoading");
            }
        }
        public Double DetailsExpanded
        {
            get { return detailsExpanded; }
            set
            {
                detailsExpanded = value;
                NotifyPropertyChanged("DetailsExpanded");
            }
        }

        private void refreshMessages()
        {
            messages = new ObservableCollection<MessageViewModel>();

            service.GetLectureMessages(lecture.Id).ToList().ForEach((message) =>
            {
                messages.Add(new MessageViewModel(message));
            });

            messageViewSource = new CollectionViewSource() { Source = messages };
            messageViewSource.View.MoveCurrentToPosition(-1);
        }

        public void Refresh()
        {
            if (!isDataLoaded)
            {
                IsDataLoaded = true;

                refreshMessages();

                persons = new ObservableCollection<PersonViewModel>();
                appointments = new ObservableCollection<AppointmentViewModel>();

                #region load data

                lecture.Persons.ForEach((person) =>
                {
                    persons.Add(new PersonViewModel(person));
                });

                appointments = new ObservableCollection<AppointmentViewModel>();
                Appointment lastAppointment = null;

                service.GetLectureAppointments(lecture.Id).ToList().ForEach((appointment) =>
                {
                    AppointmentViewModel viewModel = new AppointmentViewModel(appointment);

                    if (appointment.Recurrence == RecurrenceType.None)
                    {
                        if (lastAppointment != null)
                        {
                            if (lastAppointment.StartDate == appointment.StartDate)
                            {
                                viewModel.ShowDate = Visibility.Collapsed;

                                if (lastAppointment.StartTime == appointment.StartTime)
                                {
                                    viewModel.ShowTime = Visibility.Collapsed;
                                }
                            }
                        }

                        lastAppointment = appointment;
                    }

                    appointments.Add(viewModel);
                });



                #endregion

                personViewSource = new CollectionViewSource() { Source = persons };
                appointmentWeeklyViewSource = new CollectionViewSource() { Source = appointments };
                appointmentSingleViewSource = new CollectionViewSource() { Source = appointments };

                #region sortings/filters

                // Add filters.
                appointmentWeeklyViewSource.Filter += (o, e) =>
                {
                    e.Accepted = e.Item != null &&
                    ((AppointmentViewModel)e.Item).Recurrence != RecurrenceType.None;
                };
                appointmentSingleViewSource.Filter += (o, e) =>
                {
                    e.Accepted = e.Item != null &&
                    ((AppointmentViewModel)e.Item).Recurrence == RecurrenceType.None;
                };

                // Sort weekly appointments.
                appointmentWeeklyViewSource.SortDescriptions.Add(new SortDescription("StartDate.DayOfWeek", ListSortDirection.Ascending));
                appointmentWeeklyViewSource.SortDescriptions.Add(new SortDescription("StartTime", ListSortDirection.Ascending));

                // Reset preselection.
                personViewSource.View.MoveCurrentToPosition(-1);
                appointmentWeeklyViewSource.View.MoveCurrentToPosition(-1);
                appointmentSingleViewSource.View.MoveCurrentToPosition(-1);

                #endregion

                // Update all properties.
                NotifyPropertyChanged(String.Empty);
            }
        }
        public void SyncMessages()
        {
            IsLoading = true;

            Dispatcher dispatcher = Deployment.Current.Dispatcher;
            BackgroundWorker worker = new BackgroundWorker();

            worker.DoWork += (o, e) =>
            {
                service.SynchronizeMessages((result) =>
                {
                    dispatcher.BeginInvoke(() =>
                    {
                        refreshMessages();

                        isLoading = false;
                        NotifyPropertyChanged(String.Empty);
                    });
                });
            };

            worker.RunWorkerAsync();
        }

        public void ToggleDetails()
        {
            if (detailsExpanded == 96)
            {
                DetailsExpanded = Double.NaN;
            }
            else
            {
                DetailsExpanded = 96;
            }
        }
    }
}
